<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>SpirngCloud | 耶比大熊</title><meta name="author" content="耶比大熊,2324308799@qq.com"><meta name="copyright" content="耶比大熊"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="SpringCloud笔记   SpringCloud共分为五大组件 服务注册中心：Eureka、Zookeeper、Consul、Nacos 负载均衡：Ribbon、Feign、OpenFeign 路由网关：zuul、SpringCloudGateway 配置中心：SpringCloudConfig、Nacos 熔断降级：Hystrix、Sentinel 1CAP定理：CAP定理又称CAP原则">
<meta property="og:type" content="article">
<meta property="og:title" content="SpirngCloud">
<meta property="og:url" content="https://cxzde.cn/2024/04/07/note-springcloud/index.html">
<meta property="og:site_name" content="耶比大熊">
<meta property="og:description" content="SpringCloud笔记   SpringCloud共分为五大组件 服务注册中心：Eureka、Zookeeper、Consul、Nacos 负载均衡：Ribbon、Feign、OpenFeign 路由网关：zuul、SpringCloudGateway 配置中心：SpringCloudConfig、Nacos 熔断降级：Hystrix、Sentinel 1CAP定理：CAP定理又称CAP原则">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://tuchuang.voooe.cn/images/2024/04/07/background8.jpg">
<meta property="article:published_time" content="2024-04-07T09:00:00.000Z">
<meta property="article:modified_time" content="2024-04-07T09:00:00.000Z">
<meta property="article:author" content="耶比大熊">
<meta property="article:tag" content="blog">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://tuchuang.voooe.cn/images/2024/04/07/background8.jpg"><link rel="shortcut icon" href="/favicon.ico"><link rel="canonical" href="https://cxzde.cn/2024/04/07/note-springcloud/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css?v=4.14.0-b1"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.1/css/all.min.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>(()=>{
      const saveToLocal = {
        set: (key, value, ttl) => {
          if (ttl === 0) return
          const now = Date.now()
          const expiry = now + ttl * 86400000
          const item = {
            value,
            expiry
          }
          localStorage.setItem(key, JSON.stringify(item))
        },
      
        get: key => {
          const itemStr = localStorage.getItem(key)
      
          if (!itemStr) {
            return undefined
          }
          const item = JSON.parse(itemStr)
          const now = Date.now()
      
          if (now > item.expiry) {
            localStorage.removeItem(key)
            return undefined
          }
          return item.value
        }
      }
      
      window.btf = {
        saveToLocal: saveToLocal,
        getScript: (url, attr = {}) => new Promise((resolve, reject) => {
          const script = document.createElement('script')
          script.src = url
          script.async = true
          script.onerror = reject
          script.onload = script.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            script.onload = script.onreadystatechange = null
            resolve()
          }

          Object.keys(attr).forEach(key => {
            script.setAttribute(key, attr[key])
          })

          document.head.appendChild(script)
        }),

        getCSS: (url, id = false) => new Promise((resolve, reject) => {
          const link = document.createElement('link')
          link.rel = 'stylesheet'
          link.href = url
          if (id) link.id = id
          link.onerror = reject
          link.onload = link.onreadystatechange = function() {
            const loadState = this.readyState
            if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
            link.onload = link.onreadystatechange = null
            resolve()
          }
          document.head.appendChild(link)
        }),

        addGlobalFn: (key, fn, name = false, parent = window) => {
          const pjaxEnable = false
          if (!pjaxEnable && key.startsWith('pjax')) return

          const globalFn = parent.globalFn || {}
          const keyObj = globalFn[key] || {}
    
          if (name && keyObj[name]) return
    
          name = name || Object.keys(keyObj).length
          keyObj[name] = fn
          globalFn[key] = keyObj
          parent.globalFn = globalFn
        }
      }
    
      const activateDarkMode = () => {
        document.documentElement.setAttribute('data-theme', 'dark')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
        }
      }
      const activateLightMode = () => {
        document.documentElement.setAttribute('data-theme', 'light')
        if (document.querySelector('meta[name="theme-color"]') !== null) {
          document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
        }
      }

      btf.activateDarkMode = activateDarkMode
      btf.activateLightMode = activateLightMode
      
      const t = saveToLocal.get('theme')
    
          const now = new Date()
          const hour = now.getHours()
          const isNight = hour <= 6 || hour >= 18
          if (t === undefined) isNight ? activateDarkMode() : activateLightMode()
          else if (t === 'light') activateLightMode()
          else activateDarkMode()
        
      const asideStatus = saveToLocal.get('aside-status')
      if (asideStatus !== undefined) {
        if (asideStatus === 'hide') {
          document.documentElement.classList.add('hide-aside')
        } else {
          document.documentElement.classList.remove('hide-aside')
        }
      }
    
      const detectApple = () => {
        if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
          document.documentElement.classList.add('apple')
        }
      }
      detectApple()
    })()</script><script>const GLOBAL_CONFIG = {
  root: '/',
  algolia: undefined,
  localSearch: {"path":"/search.xml","preload":false,"top_n_per_article":1,"unescape":false,"languages":{"hits_empty":"找不到您查询的内容：${query}","hits_stats":"共找到 ${hits} 篇文章"}},
  translate: {"defaultEncoding":2,"translateDelay":0,"msgToTraditionalChinese":"繁","msgToSimplifiedChinese":"简"},
  noticeOutdate: {"limitDay":365,"position":"top","messagePrev":"It has been","messageNext":"days since the last update, the content of the article may be outdated."},
  highlight: {"plugin":"highlight.js","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":230},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  relativeDate: {
    homepage: true,
    post: true
  },
  runtime: '天',
  dateSuffix: {
    just: '刚刚',
    min: '分钟前',
    hour: '小时前',
    day: '天前',
    month: '个月前'
  },
  copyright: undefined,
  lightbox: 'fancybox',
  Snackbar: {"chs_to_cht":"你已切换为繁体中文","cht_to_chs":"你已切换为简体中文","day_to_night":"你已切换为深色模式","night_to_day":"你已切换为浅色模式","bgLight":"#49b1f5","bgDark":"#1f1f1f","position":"top-right"},
  infinitegrid: {
    js: 'https://cdn.jsdelivr.net/npm/@egjs/infinitegrid@4.11.1/dist/infinitegrid.min.js',
    buttonText: '加载更多'
  },
  isPhotoFigcaption: false,
  islazyload: true,
  isAnchor: false,
  percent: {
    toc: false,
    rightside: false,
  },
  autoDarkmode: false
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
  title: 'SpirngCloud',
  isPost: true,
  isHome: false,
  isHighlightShrink: false,
  isToc: true,
  postUpdate: '2024-04-07 17:00:00'
}</script><link rel="stylesheet" href="/css/mouse.css"><link rel="stylesheet" href="/css/iconfont/iconfont.css"><meta name="generator" content="Hexo 7.1.1"></head><body><div id="loading-box"><div class="loading-left-bg"></div><div class="loading-right-bg"></div><div class="spinner-box"><div class="configure-border-1"><div class="configure-core"></div></div><div class="configure-border-2"><div class="configure-core"></div></div><div class="loading-word">加载中...</div></div></div><script>(()=>{
  const $loadingBox = document.getElementById('loading-box')
  const $body = document.body
  const preloader = {
    endLoading: () => {
      $body.style.overflow = ''
      $loadingBox.classList.add('loaded')
    },
    initLoading: () => {
      $body.style.overflow = 'hidden'
      $loadingBox.classList.remove('loaded')
    }
  }

  preloader.initLoading()
  window.addEventListener('load',() => { preloader.endLoading() })

  if (false) {
    btf.addGlobalFn('pjaxSend', () => { preloader.initLoading() }, 'preloader_init')
    btf.addGlobalFn('pjaxComplete', () => { preloader.endLoading() }, 'preloader_end')
  }
})()</script><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src= "" data-lazy-src="/img/avatar.jpg" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><hr class="custom-hr"/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div></div></div><div class="post" id="body-wrap"><header class="not-top-img" id="page-header"><nav id="nav"><span id="blog-info"><a href="/" title="耶比大熊"><span class="site-name">耶比大熊</span></a></span><div id="menus"><div id="search-button"><span class="site-page social-icon search"><i class="fas fa-search fa-fw"></i><span> 搜索</span></span></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> 首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fas fa-archive"></i><span> 归档</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw fas fa-heart"></i><span> 关于</span></a></div></div><div id="toggle-menu"><span class="site-page"><i class="fas fa-bars fa-fw"></i></span></div></div></nav></header><main class="layout" id="content-inner"><div id="post"><div id="post-info"><h1 class="post-title">SpirngCloud</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-04-07T09:00:00.000Z" title="发表于 2024-04-07 17:00:00">2024-04-07</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-04-07T09:00:00.000Z" title="更新于 2024-04-07 17:00:00">2024-04-07</time></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span class="post-meta-wordcount"><i class="far fa-file-word fa-fw post-meta-icon"></i><span class="post-meta-label">字数总计:</span><span class="word-count">4.4k</span><span class="post-meta-separator">|</span><i class="far fa-clock fa-fw post-meta-icon"></i><span class="post-meta-label">阅读时长:</span><span>16分钟</span></span><span class="post-meta-separator">|</span><span class="post-meta-pv-cv" id="" data-flag-title="SpirngCloud"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="busuanzi_value_page_pv"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div><article class="post-content" id="article-container"><hr>
<h2 id="SpringCloud笔记"><a href="#SpringCloud笔记" class="headerlink" title="SpringCloud笔记"></a>SpringCloud笔记</h2><p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/20210615102152488.png" alt="在这里插入图片描述"></p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/20210615102309498.png" alt="在这里插入图片描述"></p>
<p><img src= "" data-lazy-src="https://gitee.com/cxz206015/images/raw/master/assets/20210617162056915.png" alt="在这里插入图片描述"></p>
<p>SpringCloud共分为五大组件</p>
<p>服务注册中心：Eureka、Zookeeper、Consul、<strong>Nacos</strong></p>
<p>负载均衡：Ribbon、Feign、<strong>OpenFeign</strong></p>
<p>路由网关：zuul、<strong>SpringCloudGateway</strong></p>
<p>配置中心：SpringCloudConfig、<strong>Nacos</strong></p>
<p>熔断降级：Hystrix、<strong>Sentinel</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">CAP定理：CAP定理又称CAP原则，指的是在一个分布式系统中，一致性（Consistency）、可用性（Availability）、分区容错性（Partition tolerance）。CAP 原则指的是，这三个要素最多只能同时实现两点，不可能三者兼顾。 一致性（C）：在分布式系统中的所有数据备份，在同一时刻是否同样的值。（等同于所有节点访问同一份最新的数据副本） 可用性（A）：在集群中一部分节点故障后，集群整体是否还能响应客户端的读写请求。（对数据更新具备高可用性） 分区容忍性（P），就是高可用性，一个节点崩了，并不影响其它的节点</span><br></pre></td></tr></table></figure>

<p><strong>安装Nacos</strong></p>
<p><strong>1.Windows安装</strong></p>
<ol>
<li><p>在 Github 下载 Nacos 安装包，并将这个安装包解压到任意非中文目录下</p>
</li>
<li><p>Nacos的默认端口是8848。也可以进入nacos的conf目录，修改application.properties配置文件中的端口</p>
</li>
<li><p>进入bin目录，执行命令启动</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">// windows命令</span><br><span class="line">startup.cmd -m standalone</span><br></pre></td></tr></table></figure>
</li>
<li><p>在浏览器输入地址：<a target="_blank" rel="noopener" href="http://127.0.0.1:8848/nacos%E8%AE%BF%E9%97%AE%EF%BC%8C%E9%BB%98%E8%AE%A4%E7%9A%84%E8%B4%A6%E5%8F%B7%E5%92%8C%E5%AF%86%E7%A0%81%E9%83%BD%E6%98%AFnacos">http://127.0.0.1:8848/nacos访问，默认的账号和密码都是nacos</a></p>
</li>
</ol>
<p><strong>2.Linux安装</strong></p>
<ol>
<li><p>安装JDK。Nacos依赖于JDK运行，上传到Linux服务器的某个目录，例如：<code>/usr/local/</code>，然后解压缩重命名为java</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf jdk-8u144-linux-x64.tar.gz</span><br><span class="line">// 配置环境变量</span><br><span class="line"><span class="built_in">export</span> JAVA_HOME=/usr/local/java</span><br><span class="line"><span class="built_in">export</span> PATH=<span class="variable">$PATH</span>:<span class="variable">$JAVA_HOME</span>/bin</span><br><span class="line">// 设置环境变量</span><br><span class="line"><span class="built_in">source</span> /etc/profile</span><br></pre></td></tr></table></figure>
</li>
<li><p>上传nacos安装包并解压。上传到Linux服务器的某个目录，例如<code>/usr/local/src</code>目录下</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// 解压缩安装包</span><br><span class="line">tar -xvf nacos-server-1.4.1.tar.gz</span><br><span class="line">// 然后删除安装包</span><br><span class="line"><span class="built_in">rm</span> -rf nacos-server-1.4.1.tar.gz</span><br></pre></td></tr></table></figure>
</li>
<li><p>配置端口，启动。端口配置同windows，在nacos&#x2F;bin目录中，输入命令启动Nacos</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sh startup.sh -m standalone</span><br></pre></td></tr></table></figure></li>
</ol>
<hr>
<h2 id="注册中心——Nacos"><a href="#注册中心——Nacos" class="headerlink" title="注册中心——Nacos"></a>注册中心——Nacos</h2><h3 id="配置Nacos"><a href="#配置Nacos" class="headerlink" title="配置Nacos"></a>配置Nacos</h3><ul>
<li>引依赖</li>
</ul>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- 父工程： --&gt;</span> </span><br><span class="line"><span class="tag">&lt;<span class="name">dependencyManagement</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span>   </span><br><span class="line">        <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-alibaba-dependencies<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span>    </span><br><span class="line">        <span class="tag">&lt;<span class="name">version</span>&gt;</span>2.2.5.RELEASE<span class="tag">&lt;/<span class="name">version</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">type</span>&gt;</span>pom<span class="tag">&lt;/<span class="name">type</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">scope</span>&gt;</span>import<span class="tag">&lt;/<span class="name">scope</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependencyManagement</span>&gt;</span></span><br></pre></td></tr></table></figure>

<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!-- nacos客户端依赖包 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<ul>
<li>配置nacos地址</li>
</ul>
<p>在每个微服务的 application.yml 中添加nacos地址，然后重启微服务</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">server-addr:</span> <span class="string">localhost:8848</span></span><br></pre></td></tr></table></figure>

<h3 id="配置Nacos集群"><a href="#配置Nacos集群" class="headerlink" title="配置Nacos集群"></a>配置Nacos集群</h3><p>修改微服务的 application.yml 文件，添加集群配置</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">server-addr:</span> <span class="string">localhost:8848</span> <span class="comment">#nacos地址</span></span><br><span class="line">      <span class="attr">discovery:</span></span><br><span class="line">        <span class="attr">cluster-name:</span> <span class="string">HZ</span> <span class="comment"># 集群名称</span></span><br></pre></td></tr></table></figure>

<p><strong>同集群优先的负载均衡</strong></p>
<p>默认的<code>ZoneAvoidanceRule</code>并不能实现根据同集群优先来实现负载均衡。</p>
<p>因此Nacos中提供了一个<code>NacosRule</code>的实现，可以优先从同集群中挑选实例。</p>
<p>1）给order-service配置集群信息</p>
<p>修改order-service的application.yml文件，添加集群配置：</p>
<figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">spring:</span><br><span class="line">  cloud:</span><br><span class="line">    nacos:</span><br><span class="line">      server-addr: localhost:8848</span><br><span class="line">      discovery:</span><br><span class="line">        cluster-name: HZ <span class="comment"># 集群名称</span></span><br></pre></td></tr></table></figure>

<p>2）修改负载均衡规则</p>
<p>修改order-service的application.yml文件，修改负载均衡规则：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">userservice:</span></span><br><span class="line">  <span class="attr">ribbon:</span></span><br><span class="line">    <span class="attr">NFLoadBalancerRuleClassName:</span> <span class="string">com.alibaba.cloud.nacos.ribbon.NacosRule</span> <span class="comment"># 负载均衡规则 </span></span><br></pre></td></tr></table></figure>

<h3 id="权重配置"><a href="#权重配置" class="headerlink" title="权重配置"></a>权重配置</h3><p>实际部署中会出现这样的场景：</p>
<p>服务器设备性能有差异，部分实例所在机器性能较好，另一些较差，我们希望性能好的机器承担更多的用户请求。</p>
<p>但默认情况下 NacosRule 是同集群内随机挑选，不会考虑机器的性能问题。</p>
<p>因此，Nacos提供了权重配置来控制访问频率，权重越大则访问频率越高。</p>
<p>在nacos控制台，找到微服务的实例列表，点击编辑，即可修改权重</p>
<blockquote>
<p><strong>注意</strong>：如果权重修改为0，则该实例永远不会被访问</p>
</blockquote>
<h3 id="环境隔离"><a href="#环境隔离" class="headerlink" title="环境隔离"></a>环境隔离</h3><p>Nacos提供了 namespace来实现环境隔离功能。</p>
<ul>
<li>nacos中可以有多个namespace</li>
<li>namespace下可以有group、service等</li>
<li>不同namespace之间相互隔离，例如不同namespace的服务互相不可见</li>
</ul>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714000101516.png" alt="image-20210714000101516" style="zoom:33%;" />



<p>1）创建namespace</p>
<p>默认情况下，所有service、data、group都在同一个namespace，名为public：</p>
<p>我们可以点击页面新增按钮，添加一个namespace，然后，填写表单就能在页面看到一个新的namespace：</p>
<p> 2）给微服务配置namespace</p>
<p>给微服务配置namespace只能通过修改配置来实现。</p>
<p>例如，修改order-service的application.yml文件：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">server-addr:</span> <span class="string">localhost:8848</span></span><br><span class="line">      <span class="attr">discovery:</span></span><br><span class="line">        <span class="attr">cluster-name:</span> <span class="string">HZ</span></span><br><span class="line">        <span class="attr">namespace:</span> <span class="string">492a7d5d-237b-46a1-a99a-fa8e98e4b0f9</span> <span class="comment"># 命名空间，填ID</span></span><br></pre></td></tr></table></figure>

<h3 id="Nacos与Eureka的区别"><a href="#Nacos与Eureka的区别" class="headerlink" title="Nacos与Eureka的区别"></a>Nacos与Eureka的区别</h3><p>Nacos的服务实例分为两种类型：</p>
<ul>
<li><p>临时实例：如果实例宕机超过一定时间，会从服务列表剔除，默认的类型。</p>
</li>
<li><p>非临时实例：如果实例宕机，不会从服务列表剔除，也可以叫永久实例。</p>
</li>
</ul>
<p>配置一个服务实例为永久实例：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">discovery:</span></span><br><span class="line">        <span class="attr">ephemeral:</span> <span class="literal">false</span> <span class="comment"># 设置为非临时实例</span></span><br></pre></td></tr></table></figure>

<p>Nacos和Eureka整体结构类似，服务注册、服务拉取、心跳等待，但是也存在一些差异：</p>
<img src= "" data-lazy-src="https://gitee.com/cxz206015/images/raw/master/assets/image-20210714001728017.png" alt="image-20210714001728017" style="zoom:67%;" />

<ul>
<li><p>Nacos与eureka的共同点</p>
<ul>
<li>都支持服务注册和服务拉取</li>
<li>都支持服务提供者心跳方式做健康检测</li>
</ul>
</li>
<li><p>Nacos与Eureka的区别</p>
<ul>
<li>Nacos支持服务端主动检测提供者状态：临时实例采用心跳模式，非临时实例采用主动检测模式</li>
<li>临时实例心跳不正常会被剔除，非临时实例则不会被剔除</li>
<li>Nacos支持服务列表变更的消息推送模式，服务列表更新更及时</li>
<li>Nacos集群默认采用AP方式，当集群中存在非临时实例时，采用CP模式；Eureka采用AP方式</li>
</ul>
</li>
</ul>
<hr>
<h2 id="配置中心——Nacos"><a href="#配置中心——Nacos" class="headerlink" title="配置中心——Nacos"></a>配置中心——Nacos</h2><h3 id="配置管理"><a href="#配置管理" class="headerlink" title="配置管理"></a>配置管理</h3><ul>
<li><p>添加配置文件</p>
<p>选择配置列表，然后在弹出的表单中，填写配置信息：</p>
</li>
</ul>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714164856664.png" alt="image-20210714164856664" style="zoom:50%;" />



<blockquote>
<p>注意：项目的核心配置，需要热更新的配置才有放到nacos管理的必要。基本不变的一些配置还是保存在微服务本地比较好。</p>
</blockquote>
<ul>
<li><p>从微服务拉取配置</p>
<p>微服务要拉取nacos中管理的配置，并且与本地的application.yml配置合并，才能完成项目启动。</p>
<p>因此spring引入了一种新的配置文件：bootstrap.yaml 文件，会在 application.yml 之前被读取，流程如下：</p>
</li>
</ul>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/L0iFYNF.png" alt="img" style="zoom:50%;" />

<p>1）引入nacos-config依赖</p>
<p>首先，在user-service服务中，引入nacos-config的客户端依赖：</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--nacos配置管理依赖--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-config<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>2）添加bootstrap.yaml</p>
<p>然后，在user-service中添加一个bootstrap.yaml文件，内容如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">userservice</span> <span class="comment"># 服务名称</span></span><br><span class="line">  <span class="attr">profiles:</span></span><br><span class="line">    <span class="attr">active:</span> <span class="string">dev</span> <span class="comment">#开发环境，这里是dev </span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">server-addr:</span> <span class="string">localhost:8848</span> <span class="comment"># Nacos地址</span></span><br><span class="line">      <span class="attr">config:</span></span><br><span class="line">        <span class="attr">file-extension:</span> <span class="string">yaml</span> <span class="comment"># 文件后缀名</span></span><br></pre></td></tr></table></figure>

<p>这里会根据spring.cloud.nacos.server-addr 获取nacos地址，再根据id来读取配置，文件id：</p>
<p><code>$&#123;spring.application.name&#125;-$&#123;spring.profiles.active&#125;.$&#123;spring.cloud.nacos.config.file-extension&#125;</code></p>
<p>3）读取nacos配置</p>
<h3 id="配置热更新"><a href="#配置热更新" class="headerlink" title="配置热更新"></a>配置热更新</h3><p>我们最终的目的，是修改nacos中的配置后，微服务中无需重启即可让配置生效，也就是<strong>配置热更新</strong>。</p>
<p>要实现配置热更新，可以使用两种方式：</p>
<ul>
<li><p>方式一</p>
<p>在@Value注入的变量所在类上添加注解@RefreshScope：</p>
</li>
</ul>
<img src= "" data-lazy-src="https://gitee.com/cxz206015/images/raw/master/assets/image-20210714171036335.png" alt="image-20210714171036335" style="zoom:50%;" />



<ul>
<li><p>方式二</p>
<p>使用@ConfigurationProperties注解代替@Value注解。</p>
<p>在user-service服务中，添加一个类，读取 patterrn.dateformat 属性：</p>
</li>
</ul>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="meta">@ConfigurationProperties(prefix = &quot;pattern&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">PatternProperties</span> &#123;</span><br><span class="line">    <span class="keyword">private</span> String dateformat;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在 UserController 中使用这个类代替 @Value：</p>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714171316124.png" alt="image-20210714171316124" style="zoom:50%;" />

<h3 id="配置共享"><a href="#配置共享" class="headerlink" title="配置共享"></a>配置共享</h3><p>其实微服务启动时，会去nacos读取多个配置文件，例如：</p>
<ul>
<li><p><code>[spring.application.name]-[spring.profiles.active].yaml</code>，例如：userservice-dev.yaml</p>
</li>
<li><p><code>[spring.application.name].yaml</code>，例如：userservice.yaml</p>
</li>
</ul>
<p>而<code>[spring.application.name].yaml</code>不包含环境，因此可以被多个环境共享。</p>
<p>1）添加一个环境共享配置</p>
<p>我们在nacos中添加一个 userservice.yaml 文件：</p>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714173233650.png" alt="image-20210714173233650" style="zoom:50%;" />



<p>2）配置共享的优先级</p>
<p>当nacos、服务本地同时出现相同属性时，优先级有高低之分：</p>
<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714174623557.png" alt="image-20210714174623557" style="zoom:50%;" />

<h3 id="Nacos集群"><a href="#Nacos集群" class="headerlink" title="Nacos集群"></a>Nacos集群</h3><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210409210621117.png" alt="image-20210409210621117" style="zoom: 67%;" />

<img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210409211355037.png" alt="image-20210409211355037" style="zoom:50%;" />

<p>搭建集群的基本步骤：</p>
<ul>
<li>搭建数据库，初始化数据库表结构</li>
<li>下载并配置nacos</li>
<li>启动nacos集群</li>
<li>nginx反向代理</li>
</ul>
<ol>
<li><p>初始化数据库</p>
<p>Nacos默认数据存储在内嵌数据库Derby中，不属于生产可用的数据库。</p>
<p>官方推荐的最佳实践是使用带有主从的高可用数据库集群</p>
</li>
<li><p>配置Nacos</p>
<p>将这个包解压到任意非中文目录下，进入nacos的conf目录，修改配置文件cluster.conf.example，重命名为cluster.conf，然后添加内容，修改application.properties文件，添加数据库配置。修改每个nacos节点的配置文件</p>
</li>
<li><p>启动</p>
</li>
</ol>
<p>   分别启动三个nacos节点：</p>
   <figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">startup.cmd</span><br></pre></td></tr></table></figure>

<ol start="4">
<li><p>nginx反向代理</p>
<p>修改conf&#x2F;nginx.conf文件，而后在浏览器访问：<a target="_blank" rel="noopener" href="http://localhost/nacos%E5%8D%B3%E5%8F%AF%E3%80%82">http://localhost/nacos即可。</a></p>
<figure class="highlight nginx"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="section">upstream</span> nacos-cluster &#123;</span><br><span class="line">    <span class="attribute">server</span> <span class="number">127.0.0.1:8845</span>;</span><br><span class="line">	<span class="attribute">server</span> <span class="number">127.0.0.1:8846</span>;</span><br><span class="line">	<span class="attribute">server</span> <span class="number">127.0.0.1:8847</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="section">server</span> &#123;</span><br><span class="line">    <span class="attribute">listen</span>       <span class="number">80</span>;</span><br><span class="line">    <span class="attribute">server_name</span>  localhost;</span><br><span class="line"></span><br><span class="line">    <span class="section">location</span> /nacos &#123;</span><br><span class="line">        <span class="attribute">proxy_pass</span> http://nacos-cluster;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>优化</p>
</li>
</ol>
<ul>
<li><p>实际部署时，需要给做反向代理的nginx服务器设置一个域名，这样后续如果有服务器迁移nacos的客户端也无需更改配置.</p>
</li>
<li><p>Nacos的各个节点应该部署到多个不同服务器，做好容灾和隔离</p>
</li>
</ul>
<h2 id="负载均衡——LoadBalance"><a href="#负载均衡——LoadBalance" class="headerlink" title="负载均衡——LoadBalance"></a>负载均衡——LoadBalance</h2><p>Ribbon实现负载均衡</p>
<p>LoadBalance实现负载均衡</p>
<h3 id="基于-RestTemplate和-LoadBalanced-注解"><a href="#基于-RestTemplate和-LoadBalanced-注解" class="headerlink" title="基于 RestTemplate和 @LoadBalanced 注解"></a>基于 RestTemplate和 @LoadBalanced 注解</h3><p><code>RestTemplate</code> 是 <strong>spring-web</strong> 包提供的, 用来调用 <strong>HTTP</strong> 接口的工具类, 它提供了 <code>GET</code>、<code>POST</code> 等常用的请求方法</p>
<ol>
<li><p>添加到 spring 容器</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="keyword">public</span> RestTemplate <span class="title function_">restTemplate</span><span class="params">()</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">RestTemplate</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>使用前注入依赖</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> RestTemplate restTemplate;</span><br></pre></td></tr></table></figure>
</li>
<li><p>常用 API</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 发送 GET 请求</span></span><br><span class="line">restTemplate.getForObject(...)</span><br><span class="line"></span><br><span class="line"><span class="comment">// 发送 POST 请求</span></span><br><span class="line">restTemplate.postForObject(...)</span><br><span class="line">  </span><br><span class="line"><span class="comment">// 自定义</span></span><br><span class="line">restTemplate.execute(...)</span><br></pre></td></tr></table></figure></li>
</ol>
<p>按照上面那种简单的写法, 我们只能调用有明确 <strong>IP</strong> 和 <strong>端口</strong> 的接口, 要想实现我们的需求, 至少要做两件事情:</p>
<ol>
<li>根据服务名拿到服务实例的信息</li>
<li>负载均衡算法</li>
</ol>
<p><code>RestTemplate</code> 提供了拦截器的功能 <code>ClientHttpRequestInterceptor</code>, 开发者可以 <strong>手动编码</strong> 实现上面两个功能. </p>
<p>Spring Cloud 使用方式如下:</p>
<ol>
<li><p>在原有基础上加上 <code>@LoadBalanced</code> 注解</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Bean</span></span><br><span class="line"><span class="meta">@LoadBalanced</span></span><br><span class="line"><span class="keyword">public</span> RestTemplate <span class="title function_">restTemplate</span><span class="params">()</span> &#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">RestTemplate</span>();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
</li>
<li><p>调用接口时,传入服务名称</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">User</span> <span class="variable">user</span> <span class="operator">=</span> restTemplate.getForObject(<span class="string">&quot;http://user-service/getUser&quot;</span>, User.class);</span><br></pre></td></tr></table></figure></li>
</ol>
<p>一个注解就帮我们完成了负载均衡</p>
<h3 id="基于-DiscoveryClient"><a href="#基于-DiscoveryClient" class="headerlink" title="基于 DiscoveryClient"></a>基于 DiscoveryClient</h3><p><code>org.springframework.cloud.client.discovery.DiscoveryClient</code> 可以帮我们实现服务发现的功能, 只要我们拿到服务对应的实例信息, 后面 <strong>负载均衡</strong> 可以手动编码实现</p>
<ol>
<li><p>注入依赖</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Autowired</span></span><br><span class="line"><span class="keyword">private</span> DiscoveryClient discoveryClient;</span><br></pre></td></tr></table></figure>
</li>
<li><p>获取注册中心服务实例列表</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">List&lt;ServiceInstance&gt; instances = discoveryClient.getInstances(<span class="string">&quot;user-service&quot;</span>);</span><br></pre></td></tr></table></figure>
</li>
<li><p>选取一个实例的地址信息, 发送请求</p>
</li>
</ol>
<h3 id="基于-Feign-的声明式调用"><a href="#基于-Feign-的声明式调用" class="headerlink" title="基于 Feign 的声明式调用"></a>基于 Feign 的声明式调用</h3><p>feign作为远程调用框架集成了ribbon实现的负载均衡，故feign的介绍在远程服务调用。</p>
<hr>
<h2 id="远程服务调用——Feign"><a href="#远程服务调用——Feign" class="headerlink" title="远程服务调用——Feign"></a>远程服务调用——Feign</h2><h3 id="类比Spring和Feign"><a href="#类比Spring和Feign" class="headerlink" title="类比Spring和Feign"></a>类比Spring和Feign</h3><p>Spring的声明式事务，只需要简单的在配置文件中告诉Spring要对谁加事务，把规则定义清楚就好了，剩下的交给spring</p>
<p>Feign的声明式Http客户端，将发请求所需要的信息声明出来，剩下的事交给Feign来做</p>
<h3 id="使用Feign的步骤"><a href="#使用Feign的步骤" class="headerlink" title="使用Feign的步骤"></a><strong>使用Feign的步骤</strong></h3><p>① 引入依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-openfeign<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>② 添加@EnableFeignClients注解</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714175102524.png" alt="image-20210714175102524"></p>
<p>③ 编写FeignClient接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@FeignClient(&quot;userservice&quot;)</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">UserClient</span> &#123;</span><br><span class="line">    <span class="meta">@GetMapping(&quot;/user/&#123;id&#125;&quot;)</span></span><br><span class="line">    User <span class="title function_">findById</span><span class="params">(<span class="meta">@PathVariable(&quot;id&quot;)</span> Long id)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>这个客户端主要是基于SpringMVC的注解来声明远程调用的信息，比如：</p>
<ul>
<li>服务名称：userservice</li>
<li>请求方式：GET</li>
<li>请求路径：&#x2F;user&#x2F;{id}</li>
<li>请求参数：Long id</li>
<li>返回值类型：User</li>
</ul>
<p>这样，Feign就可以帮助我们发送http请求，无需自己使用RestTemplate来发送了</p>
<h3 id="自定义配置"><a href="#自定义配置" class="headerlink" title="自定义配置"></a>自定义配置</h3><p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/0e0a73607da42866a8705bc55b8e66c6.png" alt="image-20220316103458187"></p>
<h3 id="Feign使用优化"><a href="#Feign使用优化" class="headerlink" title="Feign使用优化"></a>Feign使用优化</h3><ul>
<li>日志级别尽量用basic</li>
<li>使用HttpClient或OKHttp代替URLConnection</li>
</ul>
<p>Feign底层发起http请求，依赖于其它的框架。其底层客户端实现包括：</p>
<ul>
<li><p>URLConnection：默认实现，不支持连接池</p>
</li>
<li><p>Apache HttpClient ：支持连接池</p>
</li>
<li><p>OKHttp：支持连接池</p>
</li>
</ul>
<p>因此提高Feign的性能主要手段就是使用<strong>连接池</strong>代替默认的 URLConnection。</p>
<p>① 引入Apache的HttpClient依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--httpClient的依赖 --&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>io.github.openfeign<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>feign-httpclient<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>

<p>② 配置连接池</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">feign:</span></span><br><span class="line">  <span class="attr">client:</span></span><br><span class="line">    <span class="attr">config:</span></span><br><span class="line">      <span class="attr">default:</span> <span class="comment"># default全局的配置</span></span><br><span class="line">        <span class="attr">loggerLevel:</span> <span class="string">BASIC</span> <span class="comment"># 日志级别，BASIC就是基本的请求和响应信息</span></span><br><span class="line">  <span class="attr">httpclient:</span></span><br><span class="line">    <span class="attr">enabled:</span> <span class="literal">true</span> <span class="comment"># 开启feign对HttpClient的支持</span></span><br><span class="line">    <span class="attr">max-connections:</span> <span class="number">200</span> <span class="comment"># 最大的连接数</span></span><br><span class="line">    <span class="attr">max-connections-per-route:</span> <span class="number">50</span> <span class="comment"># 每个路径的最大连接数</span></span><br></pre></td></tr></table></figure>





<hr>
<h2 id="路由网关——Gateway"><a href="#路由网关——Gateway" class="headerlink" title="路由网关——Gateway"></a>路由网关——Gateway</h2><h3 id="搭建步骤："><a href="#搭建步骤：" class="headerlink" title="搭建步骤："></a>搭建步骤：</h3><ol>
<li><p>引入nacos服务发现和gateway依赖</p>
<figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">&lt;!--gateway网关--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>org.springframework.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-gateway<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br><span class="line"><span class="comment">&lt;!--nacos服务发现--&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">dependency</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">groupId</span>&gt;</span>com.alibaba.cloud<span class="tag">&lt;/<span class="name">groupId</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">artifactId</span>&gt;</span>spring-cloud-starter-alibaba-nacos-discovery<span class="tag">&lt;/<span class="name">artifactId</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">dependency</span>&gt;</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>配置application.yml，包括服务基本信息、nacos地址、路由</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">10010</span> <span class="comment"># 网关端口</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">application:</span></span><br><span class="line">    <span class="attr">name:</span> <span class="string">gateway</span> <span class="comment"># 服务名称</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">nacos:</span></span><br><span class="line">      <span class="attr">server-addr:</span> <span class="string">localhost:8848</span> <span class="comment"># nacos地址</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span> <span class="comment"># 网关路由配置</span></span><br><span class="line">        <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">user-service</span> <span class="comment"># 路由id，自定义，只要唯一即可</span></span><br><span class="line">          <span class="comment"># uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址</span></span><br><span class="line">          <span class="attr">uri:</span> <span class="string">lb://userservice</span> <span class="comment"># 路由的目标地址 lb就是负载均衡，后面跟服务名称</span></span><br><span class="line">          <span class="attr">predicates:</span> <span class="comment"># 路由断言，也就是判断请求是否符合路由规则的条件</span></span><br><span class="line">            <span class="bullet">-</span> <span class="string">Path=/user/**</span> <span class="comment"># 这个是按照路径匹配，只要以/user/开头就符合要求</span></span><br></pre></td></tr></table></figure></li>
</ol>
<p>路由配置包括：</p>
<ol>
<li><p>路由id：路由的唯一标示</p>
</li>
<li><p>路由目标（uri）：路由的目标地址，http代表固定地址，lb代表根据服务名负载均衡</p>
</li>
<li><p>路由断言（predicates）：判断路由的规则，主要为Path这种路由工程</p>
</li>
<li><p>路由过滤器（filters）：对请求或响应做处理</p>
</li>
</ol>
<h3 id="过滤器"><a href="#过滤器" class="headerlink" title="过滤器"></a>过滤器</h3><p>① 路由过滤器</p>
<p>当前过滤器写在userservice路由下，因此仅仅对访问userservice的请求有效。</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">user-service</span> </span><br><span class="line">        <span class="attr">uri:</span> <span class="string">lb://userservice</span> </span><br><span class="line">        <span class="attr">predicates:</span> </span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/user/**</span> </span><br><span class="line">        <span class="attr">filters:</span> <span class="comment"># 过滤器</span></span><br><span class="line">        <span class="bullet">-</span> <span class="string">AddRequestHeader=xxx</span> <span class="comment"># 添加请求头</span></span><br></pre></td></tr></table></figure>

<p>② 默认过滤器</p>
<p>如果要对所有的路由都生效，则可以将过滤器工厂写到default下。格式如下：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="attr">routes:</span></span><br><span class="line">      <span class="bullet">-</span> <span class="attr">id:</span> <span class="string">user-service</span> </span><br><span class="line">        <span class="attr">uri:</span> <span class="string">lb://userservice</span> </span><br><span class="line">        <span class="attr">predicates:</span> </span><br><span class="line">        <span class="bullet">-</span> <span class="string">Path=/user/**</span></span><br><span class="line">      <span class="attr">default-filters:</span> <span class="comment"># 默认过滤项</span></span><br><span class="line">      <span class="bullet">-</span> <span class="string">AddRequestHeader=Truth,</span> <span class="string">Itcast</span> <span class="string">is</span> <span class="string">freaking</span> <span class="string">awesome!</span> </span><br></pre></td></tr></table></figure>

<p>③ 全局过滤器</p>
<p><strong>作用：</strong>处理一切进入网关的请求和微服务响应，同GatewayFilter</p>
<p><strong>区别：</strong>GatewayFilter通过配置定义，处理逻辑是固定的；而GlobalFilter的定义方式是实现GlobalFilter接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">GlobalFilter</span> &#123;</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     *  处理当前请求，有必要的话通过&#123;<span class="doctag">@link</span> GatewayFilterChain&#125;将请求交给下一个过滤器处理</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> exchange 请求上下文，里面可以获取Request、Response等信息</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> chain 用来把请求委托给下一个过滤器 </span></span><br><span class="line"><span class="comment">     * <span class="doctag">@return</span> &#123;<span class="doctag">@code</span> Mono&lt;Void&gt;&#125; 返回标示当前过滤器业务结束</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    Mono&lt;Void&gt; <span class="title function_">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在filter中编写自定义逻辑，可以实现下列功能：</p>
<ul>
<li>登录状态判断</li>
<li>权限校验</li>
<li>请求限流等</li>
</ul>
<p><strong>自定义全局过滤器：</strong></p>
<p>需求：定义全局过滤器，拦截请求，判断请求的参数是否满足下面条件：</p>
<ul>
<li><p>参数中是否有authorization，</p>
</li>
<li><p>authorization参数值是否为admin</p>
</li>
</ul>
<p>如果同时满足则放行，否则拦截</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">@Order(-1)</span></span><br><span class="line"><span class="meta">@Component</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">AuthorizeFilter</span> <span class="keyword">implements</span> <span class="title class_">GlobalFilter</span> &#123;</span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> Mono&lt;Void&gt; <span class="title function_">filter</span><span class="params">(ServerWebExchange exchange, GatewayFilterChain chain)</span> &#123;</span><br><span class="line">        <span class="comment">// 1.获取请求参数</span></span><br><span class="line">        MultiValueMap&lt;String, String&gt; params = exchange.getRequest().getQueryParams();</span><br><span class="line">        <span class="comment">// 2.获取authorization参数</span></span><br><span class="line">        <span class="type">String</span> <span class="variable">auth</span> <span class="operator">=</span> params.getFirst(<span class="string">&quot;authorization&quot;</span>);</span><br><span class="line">        <span class="comment">// 3.校验</span></span><br><span class="line">        <span class="keyword">if</span> (<span class="string">&quot;admin&quot;</span>.equals(auth)) &#123;</span><br><span class="line">            <span class="comment">// 放行</span></span><br><span class="line">            <span class="keyword">return</span> chain.filter(exchange);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 4.拦截</span></span><br><span class="line">        <span class="comment">// 4.1.禁止访问，设置状态码</span></span><br><span class="line">        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);</span><br><span class="line">        <span class="comment">// 4.2.结束处理</span></span><br><span class="line">        <span class="keyword">return</span> exchange.getResponse().setComplete();</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>④ 过滤器执行顺序</p>
<p><img src= "" data-lazy-src="https://gitee.com/cxz206015/images/raw/master/assets/image-20210714214228409.png" alt="image-20210714214228409"></p>
<p>排序的规则：</p>
<ul>
<li>每一个过滤器都必须指定一个int类型的order值，<strong>order值越小，优先级越高，执行顺序越靠前</strong>。</li>
<li>GlobalFilter通过实现Ordered接口，或者添加@Order注解来指定order值</li>
<li>路由过滤器和defaultFilter的order由Spring指定，默认是按照声明顺序从1递增。</li>
<li>当过滤器的order值一样时，会按照 defaultFilter &gt; 路由过滤器 &gt; GlobalFilter的顺序执行。</li>
</ul>
<p>详细内容，可以查看源码：</p>
<p><code>org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()</code>方法是先加载defaultFilters，然后再加载某个route的filters，然后合并。</p>
<p><code>org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()</code>方法会加载全局过滤器，与前面的过滤器合并后根据order排序，组织过滤器链。</p>
<h3 id="跨域问题"><a href="#跨域问题" class="headerlink" title="跨域问题"></a>跨域问题</h3><p>跨域：域名不一致就是跨域，主要包括：</p>
<ul>
<li><p>域名不同： <a target="_blank" rel="noopener" href="http://www.taobao.com/">www.taobao.com</a> 和 <a target="_blank" rel="noopener" href="http://www.taobao.org/">www.taobao.org</a> 和 <a target="_blank" rel="noopener" href="http://www.jd.com/">www.jd.com</a> 和 miaosha.jd.com</p>
</li>
<li><p>域名相同，端口不同：localhost : 8090和localhost : 10010</p>
</li>
</ul>
<p>跨域问题：浏览器禁止请求的发起者与服务端发生跨域ajax请求，请求被浏览器拦截的问题</p>
<p><img src= "" data-lazy-src="https://cdn.jsdelivr.net/gh/cxz206015/For-PicGo@main/img/image-20210714215832675.png" alt="image-20210714215832675"></p>
<p>解决方案：<a target="_blank" rel="noopener" href="https://www.ruanyifeng.com/blog/2016/04/cors.html">CORS</a></p>
<p>在gateway服务的application.yml文件中，添加下面的配置：</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">cloud:</span></span><br><span class="line">    <span class="attr">gateway:</span></span><br><span class="line">      <span class="comment"># 。。。</span></span><br><span class="line">      <span class="attr">globalcors:</span> <span class="comment"># 全局的跨域处理</span></span><br><span class="line">        <span class="attr">add-to-simple-url-handler-mapping:</span> <span class="literal">true</span> <span class="comment"># 解决options请求被拦截问题</span></span><br><span class="line">        <span class="attr">corsConfigurations:</span></span><br><span class="line">          <span class="string">&#x27;[/**]&#x27;</span><span class="string">:</span></span><br><span class="line">            <span class="attr">allowedOrigins:</span> <span class="comment"># 允许哪些网站的跨域请求 </span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;http://localhost:8090&quot;</span></span><br><span class="line">            <span class="attr">allowedMethods:</span> <span class="comment"># 允许的跨域ajax的请求方式</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;GET&quot;</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;POST&quot;</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;DELETE&quot;</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;PUT&quot;</span></span><br><span class="line">              <span class="bullet">-</span> <span class="string">&quot;OPTIONS&quot;</span></span><br><span class="line">            <span class="attr">allowedHeaders:</span> <span class="string">&quot;*&quot;</span> <span class="comment"># 允许在请求中携带的头信息</span></span><br><span class="line">            <span class="attr">allowCredentials:</span> <span class="literal">true</span> <span class="comment"># 是否允许携带cookie</span></span><br><span class="line">            <span class="attr">maxAge:</span> <span class="number">360000</span> <span class="comment"># 这次跨域检测的有效期</span></span><br></pre></td></tr></table></figure>

<hr>
<h2 id="熔断降级——Sentinel"><a href="#熔断降级——Sentinel" class="headerlink" title="熔断降级——Sentinel"></a>熔断降级——Sentinel</h2><h2 id="分布式事务——Seata"><a href="#分布式事务——Seata" class="headerlink" title="分布式事务——Seata"></a>分布式事务——Seata</h2></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta"><i class="fas fa-circle-user fa-fw"></i>文章作者: </span><span class="post-copyright-info"><a href="https://cxzde.cn">耶比大熊</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta"><i class="fas fa-square-arrow-up-right fa-fw"></i>文章链接: </span><span class="post-copyright-info"><a href="https://cxzde.cn/2024/04/07/note-springcloud/">https://cxzde.cn/2024/04/07/note-springcloud/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta"><i class="fas fa-circle-exclamation fa-fw"></i>版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://cxzde.cn" target="_blank">耶比大熊</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"></div><div class="post_share"><div class="social-share" data-image="https://tuchuang.voooe.cn/images/2024/04/07/background8.jpg" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/css/share.min.css" media="print" onload="this.media='all'"><script src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/sharejs/dist/js/social-share.min.js" defer></script></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/2024/04/08/note-netty/" title="Netty"><img class="cover" src= "" data-lazy-src="https://tuchuang.voooe.cn/images/2024/04/07/background6.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇</div><div class="prev_info">Netty</div></div></a></div><div class="next-post pull-right"><a href="/2024/04/06/note-docker/" title="Docker"><img class="cover" src= "" data-lazy-src="https://tuchuang.voooe.cn/images/2024/04/07/background1.jpg" onerror="onerror=null;src='/img/404.jpg'" alt="cover of next post"><div class="pagination-info"><div class="label">下一篇</div><div class="next_info">Docker</div></div></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src= "" data-lazy-src="/img/avatar.jpg" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">耶比大熊</div><div class="author-info__description">隐约雷鸣 阴霾天空 但盼风雨来 能留你在此</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">10</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">0</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">0</div></a></div><a id="card-info-btn" href="https://cxzde.cn"><i></i><span>🚀异次元之旅🚀</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/cxz206015" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:2324308799@qq.com" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a><a class="social-icon" href="https://www.zhihu.com/people/ashbell" target="_blank" title="知乎"><i class="iconfont icon-zhihu-circle-fill"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content"><div style="text-align:center;"><a target="_blank" rel="noopener" href="https://www.bilibili.com/bangumi/play/ep785525/?share_source=copy_web">节选自——《凡人修仙传》86集 文戏<br></a></span>吾幼时好棋 <br>名镇乡野 <br>人皆谓神童 <br>年岁稍长 遇一山野老道 <br>三天对弈 终得一胜 <br>老道愿赌服输 施展法术 <br>通天遁地 <br>吾顿生神往 <br>遂弃棋修道 <br>可惜吾天赋一般 <br>只求矜矜业业 苦心钻研 <br>不惜远家人 抛爱侣 <br>弃友人 漂泊四海 无所依绊 <br>几经险境 <br>半生贫苦 <br>老来方有定所 <br>可惜 时日无多 <br>近来常思 <br>人生百年 蜉蝣一日 <br>长生于我何有哉 <br>不过又入樊笼尔 <br>不若二三好友 <br>弈棋饮酒 <br>良缘佳侣 人间携手 <br>风光百年 同归尘土 <br>但 <br>问道之心 <br>终归难改 <br>纵使蹉跎一生 <br>也要争那 一线天机 <br>只因幼时便知 <br>人生如棋 <br>落子 <br>无悔 <br></div></div><button></button></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#SpringCloud%E7%AC%94%E8%AE%B0"><span class="toc-number">1.</span> <span class="toc-text">SpringCloud笔记</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%B3%A8%E5%86%8C%E4%B8%AD%E5%BF%83%E2%80%94%E2%80%94Nacos"><span class="toc-number">2.</span> <span class="toc-text">注册中心——Nacos</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AENacos"><span class="toc-number">2.1.</span> <span class="toc-text">配置Nacos</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AENacos%E9%9B%86%E7%BE%A4"><span class="toc-number">2.2.</span> <span class="toc-text">配置Nacos集群</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%9D%83%E9%87%8D%E9%85%8D%E7%BD%AE"><span class="toc-number">2.3.</span> <span class="toc-text">权重配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%8E%AF%E5%A2%83%E9%9A%94%E7%A6%BB"><span class="toc-number">2.4.</span> <span class="toc-text">环境隔离</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Nacos%E4%B8%8EEureka%E7%9A%84%E5%8C%BA%E5%88%AB"><span class="toc-number">2.5.</span> <span class="toc-text">Nacos与Eureka的区别</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E4%B8%AD%E5%BF%83%E2%80%94%E2%80%94Nacos"><span class="toc-number">3.</span> <span class="toc-text">配置中心——Nacos</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E7%AE%A1%E7%90%86"><span class="toc-number">3.1.</span> <span class="toc-text">配置管理</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E7%83%AD%E6%9B%B4%E6%96%B0"><span class="toc-number">3.2.</span> <span class="toc-text">配置热更新</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E9%85%8D%E7%BD%AE%E5%85%B1%E4%BA%AB"><span class="toc-number">3.3.</span> <span class="toc-text">配置共享</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Nacos%E9%9B%86%E7%BE%A4"><span class="toc-number">3.4.</span> <span class="toc-text">Nacos集群</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E2%80%94%E2%80%94LoadBalance"><span class="toc-number">4.</span> <span class="toc-text">负载均衡——LoadBalance</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E-RestTemplate%E5%92%8C-LoadBalanced-%E6%B3%A8%E8%A7%A3"><span class="toc-number">4.1.</span> <span class="toc-text">基于 RestTemplate和 @LoadBalanced 注解</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E-DiscoveryClient"><span class="toc-number">4.2.</span> <span class="toc-text">基于 DiscoveryClient</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E5%9F%BA%E4%BA%8E-Feign-%E7%9A%84%E5%A3%B0%E6%98%8E%E5%BC%8F%E8%B0%83%E7%94%A8"><span class="toc-number">4.3.</span> <span class="toc-text">基于 Feign 的声明式调用</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E8%B0%83%E7%94%A8%E2%80%94%E2%80%94Feign"><span class="toc-number">5.</span> <span class="toc-text">远程服务调用——Feign</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E7%B1%BB%E6%AF%94Spring%E5%92%8CFeign"><span class="toc-number">5.1.</span> <span class="toc-text">类比Spring和Feign</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E4%BD%BF%E7%94%A8Feign%E7%9A%84%E6%AD%A5%E9%AA%A4"><span class="toc-number">5.2.</span> <span class="toc-text">使用Feign的步骤</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E9%85%8D%E7%BD%AE"><span class="toc-number">5.3.</span> <span class="toc-text">自定义配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#Feign%E4%BD%BF%E7%94%A8%E4%BC%98%E5%8C%96"><span class="toc-number">5.4.</span> <span class="toc-text">Feign使用优化</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E8%B7%AF%E7%94%B1%E7%BD%91%E5%85%B3%E2%80%94%E2%80%94Gateway"><span class="toc-number">6.</span> <span class="toc-text">路由网关——Gateway</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#%E6%90%AD%E5%BB%BA%E6%AD%A5%E9%AA%A4%EF%BC%9A"><span class="toc-number">6.1.</span> <span class="toc-text">搭建步骤：</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%BF%87%E6%BB%A4%E5%99%A8"><span class="toc-number">6.2.</span> <span class="toc-text">过滤器</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98"><span class="toc-number">6.3.</span> <span class="toc-text">跨域问题</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7%E2%80%94%E2%80%94Sentinel"><span class="toc-number">7.</span> <span class="toc-text">熔断降级——Sentinel</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1%E2%80%94%E2%80%94Seata"><span class="toc-number">8.</span> <span class="toc-text">分布式事务——Seata</span></a></li></ol></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2024 By 耶比大熊</div><div class="footer_custom_text">隐约雷鸣 阴霾天空 即使天无雨 我亦留此地<p><a target="_blank" href="https://hexo.io/" style="margin-inline:5px" title="博客框架为Hexo"><img src= "" data-lazy-src="https://img.shields.io/badge/Frame-Hexo-blue?style=flat&amp;logo=hexo" alt="博客框架为Hexo" ></a><a target="_blank" href="https://butterfly.js.org/" style="margin-inline:5px" title="博客主题为Butterfly"><img src= "" data-lazy-src="https://img.shields.io/badge/Theme-Butterfly-6513df?style=flat&amp;logo=bitdefender" alt="博客主题为Butterfly" ></a><a target="_blank" href="https://vercel.com/" style="margin-inline:5px" title="本站采用多线部署，主线路托管于Vercel"><img src= "" data-lazy-src="https://img.shields.io/badge/Hosted-Vercel-brightgreen?style=flat&amp;logo=Vercel" alt="本站采用多线部署，主线路托管于Vercel" ></a><a target="_blank" href="https://icp.gov.moe/?keyword=20245209" style="margin-inline:5px" title="本站已加入萌ICP豪华套餐，萌ICP备20245209号"><img src= "" data-lazy-src="https://img.shields.io/badge/%E8%90%8CICP%E5%A4%87-20245209-ff1485?style=flat&amp;logo=Bitwarden" alt="本站已加入萌ICP豪华套餐，萌ICP备20245209号" ></a><a target="_blank" href="https://github.com/" style="margin-inline:5px" title="本网站源码由Github提供存储仓库托管"><img src= "" data-lazy-src="https://img.shields.io/badge/Source-Github-d021d6?style=flat&amp;logo=GitHub" alt="本网站源码由Github提供存储仓库托管" ></a><a target="_blank" href="http://creativecommons.org/licenses/by-nc-sa/4.0/" style="margin-inline:5px" title="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可"><img src= "" data-lazy-src="https://img.shields.io/badge/Copyright-BY--NC--SA%204.0-d42328?style=flat&amp;logo=Claris" alt="本站采用知识共享署名-非商业性使用-相同方式共享4.0国际许可协议进行许可" ></a></p></div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="translateLink" type="button" title="简繁转换">繁</button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside-config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js?v=4.14.0-b1"></script><script src="/js/main.js?v=4.14.0-b1"></script><script src="/js/tw_cn.js?v=4.14.0-b1"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0.35/dist/fancybox/fancybox.umd.min.js"></script><script src="https://cdn.jsdelivr.net/npm/instant.page@5.2.0/instantpage.min.js" type="module"></script><script src="https://cdn.jsdelivr.net/npm/vanilla-lazyload@19.0.5/dist/lazyload.iife.min.js"></script><script src="https://cdn.jsdelivr.net/npm/node-snackbar@0.1.16/dist/snackbar.min.js"></script><script>(() => {
  const panguFn = () => {
    if (typeof pangu === 'object') pangu.autoSpacingPage()
    else {
      btf.getScript('https://cdn.jsdelivr.net/npm/pangu@4.0.7/dist/browser/pangu.min.js')
        .then(() => {
          pangu.autoSpacingPage()
        })
    }
  }

  const panguInit = () => {
    if (false){
      GLOBAL_CONFIG_SITE.isPost && panguFn()
    } else {
      panguFn()
    }
  }

  btf.addGlobalFn('pjaxComplete', panguInit, 'pangu')
  document.addEventListener('DOMContentLoaded', panguInit)
})()</script><div class="js-pjax"></div><script defer src="https://cdn.jsdelivr.net/gh/cxz206015/live2d-widget/autoload.js"></script><script id="canvas_nest" defer="defer" color="0,0,255" opacity="0.7" zIndex="-1" count="30" mobile="false" src="https://cdn.jsdelivr.net/npm/butterfly-extsrc@1.1.3/dist/canvas-nest.min.js"></script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i><span>  数据库加载中</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"/></div></div><hr/><div id="local-search-results"></div><div id="local-search-stats-wrap"></div></div></div><div id="search-mask"></div><script src="/js/search/local-search.js?v=4.14.0-b1"></script></div></div></body></html>